package site.codeyin.javautils.service;

import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.Iterables;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author <a href="https://github.com/liangcheng2221">yinjie</a>
 * @date 2024-10-13 13:03
 */
public abstract class CacheInfoService<IN, OUT> {

    private LoadingCache<IN, OUT> cache;
    private Class<IN> inClass;

    protected CacheInfoService() {
        init(60, 10 * 60, 1024);
    }
    protected CacheInfoService(long refreshSeconds, long expireSeconds, int maxSize) {
        init(refreshSeconds,expireSeconds,maxSize);
    }


    private void init(long refreshSeconds, long expireSeconds, int maxSize) {
        ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.inClass = (Class<IN>) genericSuperclass.getActualTypeArguments()[0];

        cache = Caffeine.newBuilder()
                //自动刷新,不会阻塞线程,其他线程返回旧值
                .refreshAfterWrite(refreshSeconds, TimeUnit.SECONDS)
                .expireAfterWrite(expireSeconds, TimeUnit.SECONDS)
                .maximumSize(maxSize)
                .build(new CacheLoader<IN, OUT>() {
                    @Nullable
                    @Override
                    public OUT load(@NonNull IN in) throws Exception {
                        return CacheInfoService.this.load(Collections.singletonList(in)).get(in);
                    }

                    @Override
                    public @NonNull Map<IN, OUT> loadAll(@NonNull Iterable<? extends IN> keys) throws Exception {
                        IN[] ins = Iterables.toArray(keys, inClass);
                        return CacheInfoService.this.load(Arrays.asList(ins));
                    }
                });
    }

     protected abstract Map<IN, OUT> load(List<IN> req);

    /**
     * 获取缓存信息
     *
     * @param key 缓存key
     * @return 缓存信息
     */
     public abstract OUT getCacheInfo(IN key);

    /**
     * 设置缓存信息
     *
     * @param key   缓存key
     * @param value 缓存值
     */
    public abstract void setCacheInfo(IN key, OUT value);

    /**
     * 删除缓存信息
     *
     * @param key 缓存key
     */
    public abstract void deleteCacheInfo(IN key);

    public static void main(String[] args) {
        CacheInfoService<String, Object> objectObjectCacheInfoService = new CacheInfoService<String,Object>() {

            @Override
            protected Map<String, Object> load(List<String> req) {
                return null;
            }

            @Override
            public Object getCacheInfo(String key) {
                return null;
            }

            @Override
            public void setCacheInfo(String key, Object value) {

            }

            @Override
            public void deleteCacheInfo(String key) {

            }
        };
        ParameterizedType genericSuperclass = (ParameterizedType) objectObjectCacheInfoService.getClass().getGenericSuperclass();
        System.out.println(genericSuperclass.getActualTypeArguments()[1]);
    }
}
